package com.platform.file.controller;

import ch.qos.logback.core.util.FileUtil;
import cn.hutool.core.date.StopWatch;
import com.alibaba.fastjson.JSONObject;
import com.platform.common.core.constant.CacheConstants;
import com.platform.common.core.domain.R;
import com.platform.common.core.exception.ServiceException;
import com.platform.common.core.utils.DateUtils;
import com.platform.common.core.utils.StringUtils;
import com.platform.common.core.utils.file.FileUtils;
import com.platform.common.redis.service.RedisService;
import com.platform.common.security.utils.AESUtil_SC;
import com.platform.file.constant.SysFileConstants;
import com.platform.file.model.SysFile;
import com.platform.file.model.SysFileDto;
import com.platform.file.service.IDicFileLogService;
import com.platform.file.service.ISysFileService;
import com.platform.file.utils.FileUploadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import javax.annotation.Resource;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 文件请求处理
 *
 * @author mbtec
 */
@RestController
@RequestMapping("/remote")
public class SysFileController {
    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);

    @Autowired
    private ISysFileService sysFileService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private IDicFileLogService fileLogService;
    /**
     * 资源映射路径 前缀
     */
    @Value("${minio.filePrefix}")
    ///statics
    public String filePrefix;
    @Value("${minio.bucketName}")
    ///statics
    public String bucketName;
    @Resource
    private IDicFileLogService dicFileLogService;
    @Value("${share.file.downloadPrefix}")
    private String shareFileDownloadPrefix;

    /**
     * 旧版本，禁用  完整路径请求
     */
    @PostMapping("/upload")
    public R<SysFile> upload(MultipartFile file, @RequestParam(name = "serviceName") String serviceName, String type) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        String cataloguePrefix = SysFileConstants.BUCKET_MAP.get(type);
        //默认公共文件
        cataloguePrefix = SysFileConstants.PUBLIC;
        if (StringUtils.isEmpty(serviceName)) {
            serviceName = SysFileConstants.SERVICENAME_SYS;
        }
        String url = "";
        String returnPath = filePrefix + '/' + bucketName + '/';
        String fileUrlSecret = null;
        try {
            // 上传并返回访问地址
            url = sysFileService.upload(file, serviceName, cataloguePrefix);
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(url));
            sysFile.setUrl(returnPath + url);
            fileUrlSecret = AESUtil_SC.encryptNoBase64(bucketName + "/" + url, SysFileConstants.FILESECRET);
            return R.ok(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        } finally {
            fileLogService.saveUploadLogNew(serviceName, file, url, bucketName, fileUrlSecret, cataloguePrefix, SysFileConstants.FILETAG_OTHER);
            stopWatch.stop();
            log.info("上传文件名的路径为{},上传耗时{}秒", url, stopWatch.getTotalTimeSeconds());
        }
    }

    /**
     * 返回的 文件全路径
     *
     * @param file        文件
     * @param serviceName 服务名
     * @param type        文件存储分区：3=内部公开文件夹(需要走平台认证，仅限内部人访问，文件无权限),
     *                    2=公开文件(不需要走平台认证)
     *                    1=部门级文件夹(需要走平台认证,部门文档,有权限，有权限)
     *                    0=私有文件(适合小团队或者个人文档)
     * @param fileTag     文件标签(0=其他，1=报关单，2=邮件类文件,3=板车垫板,4=报告,5=鉴定报告,6=设备维修，7=通知与新闻，8=异常上报，9=交接，10=分拣清点，11=入库称重、组板调货......按模块定义好)
     * @return
     */
    @PostMapping("/uploadNew")
    public R<SysFile> uploadNew(MultipartFile file, @RequestParam(name = "serviceName") String serviceName, String type, String fileTag) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        String cataloguePrefix = SysFileConstants.BUCKET_MAP.get(type);
        //默认公共文件
        if (StringUtils.isEmpty(cataloguePrefix)) {
            //默认公共文件
            cataloguePrefix = SysFileConstants.PUBLIC;
        }
        if (StringUtils.isEmpty(serviceName)) {
            serviceName = SysFileConstants.SERVICENAME_SYS;
        }
        String url = "";
        String returnPath = filePrefix + '/' + bucketName + '/';
        String fileUrlSecret = "";
        try {
            // 上传并返回访问地址
            url = sysFileService.upload(file, serviceName, cataloguePrefix);
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(url));
            sysFile.setUrl(returnPath + url);
            fileUrlSecret = AESUtil_SC.encryptNoBase64(bucketName + "/" + url, SysFileConstants.FILESECRET);
            return R.ok(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        } finally {
            fileLogService.saveUploadLogNew(serviceName, file, url, bucketName, fileUrlSecret, cataloguePrefix, fileTag);
            stopWatch.stop();
            log.info("上传文件名的路径为{},上传耗时{}秒", url, stopWatch.getTotalTimeSeconds());
        }
    }

    /**
     * 返回的 文件全路径
     *
     * @param file        文件
     * @param serviceName 服务名
     * @param type        文件存储分区：3=内部公开文件夹(需要走平台认证，仅限内部人访问，文件无权限),
     *                    2=公开文件(不需要走平台认证)
     *                    1=部门级文件夹(需要走平台认证,部门文档,有权限，有权限)
     *                    0=私有文件(适合小团队或者个人文档)
     * @param fileTag     文件标签(0=其他，1=报关单，2=邮件类文件,3=板车垫板,4=报告,5=鉴定报告,6=设备维修，7=通知与新闻，8=异常上报，9=交接，10=分拣清点，11=入库称重、组板调货......按模块定义好)
     * @return
     */
    @PostMapping("/uploadShareFile")
    public R<SysFile> uploadShareFile(MultipartFile file, @RequestParam(name = "serviceName") String serviceName, String type, String fileTag) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        String cataloguePrefix = SysFileConstants.BUCKET_MAP.get(type);
        //默认公共文件
        if (StringUtils.isEmpty(cataloguePrefix)) {
            //默认公共文件
            cataloguePrefix = SysFileConstants.PUBLIC;
        }
        if (StringUtils.isEmpty(serviceName)) {
            serviceName = SysFileConstants.SERVICENAME_SYS;
        }
        String url = "";
        String fileUrlSecret = "";
        String suffix = FileUploadUtils.getExtension(file.getOriginalFilename());
        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + suffix;
        String xpath = getDatePath(LocalDate.now());
        String filePath = bucketName + "/" + SysFileConstants.NO_PERMISSION + "/" + serviceName + "/" + xpath + "/" + fileName;
        String savePath = filePath.replaceFirst(bucketName + "/", "");
        try {
            sysFileService.uploadShareFile(file, savePath);
            fileUrlSecret = AESUtil_SC.encryptNoBase64(bucketName + "/" + url, SysFileConstants.FILESECRET);
            String fileKey = UUID.randomUUID().toString().replaceAll("-", "");
            dicFileLogService.saveShareFile(serviceName, fileName, filePath, bucketName, file.getContentType(), new BigDecimal(file.getSize()), fileKey);
            SysFile sysFile = new SysFile();
            sysFile.setName(fileName);
            sysFile.setUrl(shareFileDownloadPrefix+fileKey);
            return R.ok(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        } finally {
            fileLogService.saveUploadLogNew(serviceName, file, url, bucketName, fileUrlSecret, cataloguePrefix, fileTag);
            stopWatch.stop();
            log.info("上传文件名的路径为{},上传耗时{}秒", url, stopWatch.getTotalTimeSeconds());
        }
    }

    private String getFileSuffixByContentType(String contentType) {
        if (StringUtils.isBlank(contentType)) {
            throw new ServiceException("contentType为空");
        }
        switch (contentType) {
            case "image/jpeg":
                return "jpeg";
            case "image/jpg":
                return "jpg";
            case "image/png":
                return "png";
            case "text/plain":
                return "txt";
            case "docx":
            case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
                return "docx";
            case "application/pdf":
                return "pdf";
            case "application/vnd.ms-excel":
                return "xls";
            default:
                return "unknown";
        }
    }
    private String getDatePath(LocalDate date) {
        String dayOfMonth = String.format("%02d", date.getDayOfMonth());
        String month = String.format("%02d", date.getMonth().getValue());
        int year = date.getYear();
        return String.join("/", String.valueOf(year), month, dayOfMonth);
    }
    /**
     * 旧版本，禁用 完整路径请求(自定义文件名)
     */
    @PostMapping("/uploadByFileName")
    public R<SysFile> uploadByFileName(MultipartFile file, @RequestParam(name = "serviceName") String serviceName, @RequestParam(name = "fileName") String fileName, String type) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        String cataloguePrefix = SysFileConstants.BUCKET_MAP.get(type);
        //默认公共文件
        cataloguePrefix = SysFileConstants.PUBLIC;
        if (StringUtils.isEmpty(serviceName)) {
            serviceName = SysFileConstants.SERVICENAME_SYS;
        }
        String url = "";
        String returnPath = filePrefix + '/' + bucketName + '/';
        url = cataloguePrefix + "/" + serviceName + "/" + DateUtils.dateTimeNow("yyyy/MM/dd") + "/" + fileName;
        try {
            //异步调用文件上传
            try {
                sysFileService.uploadByAsyncFileName(file.getInputStream(), url, file.getContentType());
            } catch (Exception e) {
                e.printStackTrace();
            }

            // 上传并返回访问地址
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(url));
            sysFile.setUrl(returnPath + url);
            return R.ok(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        } finally {
            fileLogService.saveUploadLog(serviceName, file, url);
            stopWatch.stop();
            log.info("上传文件名的路径为{},上传耗时{}秒", url, stopWatch.getTotalTimeSeconds());
        }
    }

    /**
     * 返回的 文件全路径 (可自定义文件名)
     *
     * @param file        文件
     * @param serviceName 服务名
     * @param fileName    文件名
     * @param type        文件存储分区：2=公开文件(不需要走平台认证)，固定type =2，只有完全公开的文件才调此接口
     * @param fileTag     文件标签(0=其他，1=报关单，2=邮件类文件,3=板车垫板,4=报告,5=鉴定报告,6=设备维修，7=通知与新闻，8=异常上报，9=交接，10=分拣清点，11=入库称重、组板调货......按模块定义好)
     * @return
     */
    @PostMapping("/uploadByFileNameNewPath")
    public R<SysFile> uploadByFileNameNewPath(MultipartFile file, @RequestParam(name = "serviceName") String serviceName, @RequestParam(name = "fileName") String fileName, String type, String fileTag) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        String cataloguePrefix = SysFileConstants.BUCKET_MAP.get(type);
        //默认公共文件
        if (StringUtils.isEmpty(cataloguePrefix)) {
            //默认公共文件
            cataloguePrefix = SysFileConstants.PUBLIC;
        }
        if (StringUtils.isEmpty(serviceName)) {
            serviceName = SysFileConstants.SERVICENAME_SYS;
        }
        String url = "";
        String returnPath = filePrefix + '/' + bucketName + '/';
        url = cataloguePrefix + "/" + serviceName + "/" + DateUtils.dateTimeNow("yyyy/MM/dd") + "/" + fileName;
        String fileUrlSecret = "";
        try {
            //异步调用文件上传
            try {
                sysFileService.uploadByAsyncFileName(file.getInputStream(), url, file.getContentType());
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 上传并返回访问地址
            SysFile sysFile = new SysFile();
            sysFile.setName(FileUtils.getName(url));
            sysFile.setUrl(returnPath + url);
            fileUrlSecret = AESUtil_SC.encryptNoBase64(bucketName + "/" + url, SysFileConstants.FILESECRET);
            return R.ok(sysFile);
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        } finally {
            fileLogService.saveUploadLogNew(serviceName, file, url, bucketName, fileUrlSecret, cataloguePrefix, fileTag);
            stopWatch.stop();
            log.info("上传文件名的路径为{},上传耗时{}秒", url, stopWatch.getTotalTimeSeconds());
        }
    }

    /**
     * 上传文件
     *
     * @param
     * @param
     * @return
     */
    @PostMapping("/testdoc")
    public R<List<String>> testdoc(MultipartFile[] files, @RequestParam(name = "serviceName") String serviceName) throws Exception {
        if (StringUtils.isEmpty(serviceName)) {
            serviceName = SysFileConstants.SERVICENAME_SYS;
        }
        SysFileDto sysFileDto = new SysFileDto();
        List<Map<String, String>> fileList = new ArrayList<>();
        for (MultipartFile file : files) {
            try {
                InputStream inputStream = file.getInputStream();
                Map<String, String> map = new HashMap<>();
                map.put("data", inputStream2Base64(inputStream));
                String originalFilename = file.getOriginalFilename();
                map.put("name", originalFilename);
                fileList.add(map);

            } catch (Exception e) {
                e.printStackTrace();
            } finally {

            }
        }

        sysFileDto.setFiles(fileList);
        sysFileDto.setServiceName(serviceName);
        return uploadFile(sysFileDto);
    }

    /**
     * 上传文件
     *
     * @param
     * @param
     * @return
     */
    @PostMapping("/uploadFile")
    public R<List<String>> uploadFile(@RequestBody SysFileDto dto) {
        if (dto == null) {
            return R.fail("上传文件不能为空");
        }
        String type = dto.getType();
        String cataloguePrefix = SysFileConstants.BUCKET_MAP.get(type);
        if (StringUtils.isEmpty(cataloguePrefix)) {
            //默认公共文件
            cataloguePrefix = SysFileConstants.PUBLIC;
        }

        String serviceName = dto.getServiceName();
        List<Map<String, String>> files = dto.getFiles();
        if (StringUtils.isEmpty(serviceName)) {
            serviceName = SysFileConstants.SERVICENAME_SYS;
        }
        if (files == null || files.size() == 0) {
            return R.fail("上传文件不能为空");
        }
        R<List<String>> result = R.ok();
        List<String> filePathList = new ArrayList<>();
        for (int i = 0; i < files.size(); i++) {
            String filePath = "";
            double reSize = 0;
            try {
                Map<String, String> file = files.get(i);
                String fileName = file.get("name");
                String base64Str = file.get("data");
                //判断文件大小是否超过20MB
                reSize = this.getFileSize(base64Str);
                if ((reSize / 1024 / 1024) > SysFileConstants.FILE_MAX_VALUE) {
                    return R.fail(R.FAIL, "文件大小不能超过20MB，请重新上传");
                }
                String contentType = getContentType(fileName);
                if (base64Str != null && base64Str.contains(",")) {
                    base64Str = base64Str.split(",")[1];
                }
                Base64.Decoder decoder = Base64.getDecoder();
                byte[] decode = decoder.decode(base64Str);
                ByteArrayInputStream bArray = new ByteArrayInputStream(decode);
                filePath = cataloguePrefix + "/" + serviceName + "/" + System.currentTimeMillis() + "_" + fileName;
                String uploadFilePath = sysFileService.uploadFile(filePath, bArray, contentType);
                filePathList.add(uploadFilePath);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("上传文件失败", e);
                return R.fail(e.getMessage());
            } finally {
                fileLogService.saveUploadLog(serviceName, filePath, reSize);
            }
        }
        result.setData(filePathList);
        return result;
    }

    /**
     * 上传文件
     *
     * @param
     * @param
     * @return
     */
    @PostMapping("/uploadmultipartFile")
    public R<String> uploadmultipartFile(MultipartFile file, @RequestParam(name = "serviceName") String serviceName, String type) throws Exception {
        String cataloguePrefix = SysFileConstants.BUCKET_MAP.get(type);
        if (StringUtils.isEmpty(cataloguePrefix)) {
            //默认公共文件
            cataloguePrefix = SysFileConstants.PUBLIC;
        }
        if (StringUtils.isEmpty(serviceName)) {
            serviceName = SysFileConstants.SERVICENAME_SYS;
        }
        R<String> result = R.ok();
        String returnPath = "";
        try {
            // 上传并返回访问地址
            returnPath = sysFileService.upload(file, serviceName, cataloguePrefix);
            result.setData(returnPath);
            return result;
        } catch (Exception e) {
            log.error("上传文件失败", e);
            return R.fail(e.getMessage());
        } finally {
            fileLogService.saveUploadLog(serviceName, file, returnPath);
        }
    }

    /**
     * 获取文件流+guid校验
     */
    @GetMapping("/getInputStream")
    public void getInputStream(@RequestParam(value = "fileName") String fileName, @RequestParam(value = "guid") String guid, HttpServletResponse response) {
        try {
            //guid权限校验
            if (StringUtils.isEmpty(guid)) {
                returnResponseResult(response, R.FAIL, "guid权限校验失败");
                return;
            } else {
                if (redisService.hasKey(guid)) {
                    Integer num = redisService.getCacheObject(guid);
                    if (num == null || num.equals(SysFileConstants.ZERO)) {
                        returnResponseResult(response, R.FAIL, "guid权限校验失败");
                    }
                    //访问次数-1
                    num--;
                    if (num > SysFileConstants.ZERO) {
                        //修改次数
                        redisService.setCacheObject(guid, num);
                    } else if (num.equals(SysFileConstants.ZERO)) {
                        //删除
                        redisService.deleteObject(guid);
                    }
                } else {
                    returnResponseResult(response, R.FAIL, "guid权限校验失败");
                }

            }
            //参数校验
            if (StringUtils.isEmpty(fileName)) {
                returnResponseResult(response, R.FAIL, "文件名不能为空");
                return;
            } else {
                try {
                    String returnPath = filePrefix + '/' + bucketName + '/';
                    if (fileName.contains(returnPath)) {
                        //去除文件名前缀
                        fileName = fileName.substring(returnPath.length());
                    }
                    InputStream fileStream = sysFileService.downLoadFile(fileName);
                    if (fileStream != null) {
                        //如果需要下载文件，去掉下面的注释
//                response.setHeader("content-disposition", "attachment;");
                        OutputStream outputStream = response.getOutputStream();
                        int len = 0;
                        byte[] data = new byte[1024];
                        while ((len = fileStream.read(data)) != -1) {
                            outputStream.write(data, 0, len);
                        }
                        outputStream.close();
                        fileStream.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("获取文件流失败", e);
                } finally {
                    fileLogService.saveSelectLog(fileName);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传SDK请求PDF
     *
     * @param
     * @param
     * @return
     */
    @PostMapping("/uploadFileForSDK")
    public R<List<String>> uploadFileForSDK(@RequestBody SysFileDto dto) {
        if (dto == null) {
            return R.fail("上传文件不能为空");
        }
        String type = dto.getType();
        String cataloguePrefix = SysFileConstants.BUCKET_MAP.get(type);
        if (StringUtils.isEmpty(cataloguePrefix)) {
            //默认公共文件
            cataloguePrefix = SysFileConstants.PUBLIC;
        }

        String serviceName = dto.getServiceName();
        List<Map<String, String>> files = dto.getFiles();
        if (StringUtils.isEmpty(serviceName)) {
            serviceName = SysFileConstants.SERVICENAME_SYS;
        }
        if (files == null || files.size() == 0) {
            return R.fail("上传文件不能为空");
        }
        R<List<String>> result = R.ok();

        List<String> filePathList = new ArrayList<>();
        for (int i = 0; i < files.size(); i++) {
            String filePath = "";
            double reSize = 0;
            try {
                Map<String, String> file = files.get(i);
                String fileName = file.get("name");
                String base64Str = file.get("data");
                //判断文件大小是否超过20MB
                reSize = this.getFileSize(base64Str);
                if ((reSize / 1024 / 1024) > SysFileConstants.FILE_MAX_VALUE) {
                    return R.fail(R.FAIL, "文件大小不能超过20MB，请重新上传");
                }
                String contentType = getContentType(fileName);
                if (base64Str != null && base64Str.contains(",")) {
                    base64Str = base64Str.split(",")[1];
                }
                BASE64Decoder base64Decoder = new BASE64Decoder();
                byte[] decoded = base64Decoder.decodeBuffer(base64Str);
                ByteArrayInputStream bArray = new ByteArrayInputStream(decoded);
                filePath = cataloguePrefix + "/" + serviceName + "/" + System.currentTimeMillis() + "_" + fileName;
                String uploadFilePath = sysFileService.uploadFile(filePath, bArray, contentType);
                filePathList.add(uploadFilePath);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("上传文件失败", e);
                return R.fail(e.getMessage());
            } finally {
                fileLogService.saveUploadLog(serviceName, filePath, reSize);
            }
        }
        result.setData(filePathList);

        return result;
    }

    /**
     * 删除文件
     *
     * @param
     * @param
     * @return
     */
    @PostMapping("/deleteFile")
    public R deleteFile(String fileName) {

        if (fileName == null || fileName == "") {
            return R.fail("删除文件路径不能为空");
        }
        String returnPath = filePrefix + '/' + bucketName + '/';
        R result = R.ok();
        try {
            //删除
            if (StringUtils.isNotEmpty(fileName)) {
                String[] pathAn = fileName.split(";");
                for (String path : pathAn) {
                    if (path.contains(returnPath)) {
                        //需要删除的文件为 完整路径
                        Integer index = path.indexOf(returnPath);
                        if (index == 0) {
                            path = path.substring(returnPath.length());
                        }
                    }
                    sysFileService.deleteFile(path);

                }
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail(e.getMessage());
        } finally {

            if (StringUtils.isNotEmpty(fileName)) {
                String[] pathAn = fileName.split(";");
                for (String path : pathAn) {
                    if (path.contains(returnPath)) {
                        //需要删除的文件为 完整路径
                        Integer index = path.indexOf(returnPath);
                        if (index == 0) {
                            path = path.substring(returnPath.length());
                        }
                    }
                    fileLogService.saveDeleteLog(path);

                }
            }
        }
    }

    /**
     * 获取 图片回显的 guid
     *
     * @return
     * @throws Exception
     */
    @PostMapping("/getGuid")
    public R getGuid(@RequestParam("num") Integer num) {
        try {
            R responseResult = R.ok();
            String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
            //后端限制最大访问次数
            if (num > SysFileConstants.MAX_NUM) {
                num = SysFileConstants.MAX_NUM;
            }
            redisService.setCacheObject(uuid, num, CacheConstants.EXPIRATION, TimeUnit.MINUTES);
            responseResult.setData(uuid);
            return responseResult;

        } catch (Exception e) {
            e.printStackTrace();
            return R.fail(e.getMessage());
        }
    }


    /**
     * 限制文件上传大小(不能超过20MB)
     *
     * @param base64Str
     * @return
     */
    public double getFileSize(String base64Str) {
        //检测是否含有base64,文件头)
        if (base64Str.lastIndexOf(",") > 0) {
            base64Str = base64Str.substring(base64Str.lastIndexOf(",") + 1);
        }
        // 获取base64字符串长度(不含data:audio/wav;base64,文件头)
        int size0 = base64Str.length();
        // 获取字符串的尾巴的最后10个字符，用于判断尾巴是否有等号，正常生成的base64文件'等号'不会超过4个
        String tail = base64Str.substring(size0 - 10);
        // 找到等号，把等号也去掉,(等号其实是空的意思,不能算在文件大小里面)
        int equalIndex = tail.indexOf("=");
        if (equalIndex > 0) {
            size0 = size0 - (10 - equalIndex);
        }
        // 计算后得到的文件流大小，单位为字节
        double reSize = size0 - ((double) size0 / 8) * 2;

        return reSize;
    }

    /**
     * 返回响应信息
     */
    private void returnResponseResult(ServletResponse response, int code, String msg) throws IOException {
        PrintWriter writer = null;
        OutputStreamWriter osw = null;
        try {
            osw = new OutputStreamWriter(response.getOutputStream(), "GBK");
            writer = new PrintWriter(osw, true);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", code);
            jsonObject.put("message", msg);
            writer.write(jsonObject.toJSONString());
            writer.flush();
            writer.close();
            osw.close();
        } catch (Exception e) {
        } finally {
            if (null != writer) {
                writer.close();
            }
            if (null != osw) {
                osw.close();
            }
        }
    }

    /**
     * base64编码
     *
     * @param is
     * @return
     * @throws Exception
     */
    public static String inputStream2Base64(InputStream is) throws Exception {
        byte[] data = null;
        try {
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = is.read(buff, 0, 100)) > 0) {
                swapStream.write(buff, 0, rc);
            }
            data = swapStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    throw new Exception("输入流关闭异常");
                }
            }
        }

        return Base64.getEncoder().encodeToString(data);
    }

    public String getContentType(String fileName) {
        String contentType;
        int idx;
        String suffix = "";
        if ((idx = fileName.lastIndexOf(".")) > 0) {
            suffix = fileName.substring(idx + 1);
        }
        if ("".equals(suffix)) {
            return null;
        }
        switch (suffix) {
            case "jpg":
            case "jpeg":
                contentType = "image/jpeg";
                break;
            case "png":
                contentType = "image/png";
                break;
            case "txt":
                contentType = "text/plain";
                break;
            case "sql":
            case "md":
            case "xmind":
            case "lrc":
                contentType = "application/octet-stream";
                break;
            case "docx":
            case "doc":
                contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
                break;
            case "pdf":
                contentType = "application/pdf";
                break;
            case "xls":
                contentType = "application/vnd.ms-excel";
                break;
            default:
                contentType = suffix;
        }
        return contentType;
    }
}
